package com.front.web.lvyouXcxWeb;

import com.alibaba.druid.util.StringUtils;
import com.bootdo.common.utils.*;
import com.bootdo.common.wxpay.*;
import com.bootdo.haojiangboutils.MapBuild;
import com.bootdo.haojiangboutils.RequestParCheckUtils;
import com.bootdo.haojiangboutils.ResultReBuild;
import com.bootdo.lvyou.domain.*;
import com.bootdo.lvyou.service.LvyouMemberService;
import com.bootdo.netty.common.CtxRefList;
import com.bootdo.netty.model.SmartCarProtocol;
import io.netty.channel.Channel;

import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@RequestMapping("/f/scenicspot/order/v1/")
@RestController
public class ScenicSpotOrderControllerV1 extends LvyouSupperController{

    public static final String WXPAYOK="<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
    public static final String WXPAYNO="<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[支付失败]]></return_msg></xml>";
    public static Lock LOCK = new ReentrantLock();
   /* public static String apiKey ="79168e5f202ec2409f3ce8aedec68354";
    public static String appId="wxd0c1325626458eb0";
    public static String memchantNo ="1536471061";*/


    /**
     * http://127.0.0.1/f/scenicspot/order/v1/get_order_list?mobile=15230060935&pageNo=0&pageSize=5
     * @param mobile
     * @param pageNo
     * @param pageSize
     * @param request
     * @return
     */
    @RequestMapping("/get_order_list")
    @ResponseBody
    public R getOrderByList(
            @RequestParam("mobile") String mobile,
            @RequestParam("pageNo") Integer pageNo,
            @RequestParam("pageSize") Integer pageSize,
            @RequestParam("status") Integer status,
            HttpServletRequest request){
        MapBuild mapBuild = new MapBuild();
        mapBuild.setKV("memberMobile", mobile);
        mapBuild.setKV("offset", pageNo * pageSize);
        mapBuild.setKV("limit", pageSize);
        // 全部
        if(status.intValue() == 0){

        }else if(status.intValue() == 1){
            mapBuild.setKV("status", 2);
        }else if(status.intValue() == 2){
            mapBuild.setKV("status", 5);
        }
        int count = lvyouScenicTicketOrderService.count(mapBuild);
        int pageSum=(count-1)/pageSize+1;

        if(pageNo > pageSum-1){
            return R.error("没有更多了");
        }
        List<LvyouScenicTicketOrder> lvyouScenicTicketOrders =  lvyouScenicTicketOrderService.list(mapBuild);
        if(lvyouScenicTicketOrders.size() == 0){
            return R.error("没有更多了");
        }
        return R.ok().put("l", lvyouScenicTicketOrders);
    }




    /**
     * http://127.0.0.1/f/scenicspot/order/v1/hexiao?orderNo=LV636200068011831296&mobile=
     * @param request
     * @return
     */
    @RequestMapping("/hexiao")
    @ResponseBody
    public R hexiaoOrder(
            @RequestParam("orderNo") String orderNo,
            @RequestParam("mobile") String mobile,
            HttpServletRequest request){

        Date now = DateUtils.getCustomTime(0);
        LvyouScenicTicketOrder lvyouScenicTicketOrder =  lvyouScenicTicketOrderService.getByOrderNoAndStatus(orderNo, 2);
        if(null == lvyouScenicTicketOrder){
            return R.error("该订单不存在,请注意");
        }
        if(!lvyouScenicTicketOrder.getTicketDate().equals(now)){
            if(lvyouScenicTicketOrder.getTicketDate().before(now)){
                return R.error("门票已过期");
            }else{
                return R.error("门票未到使用时间");
            }
        }

        LvyouMember lvyouMember =  lvyouMemberService.getByMobile(mobile);
        if(null == lvyouMember){
            return R.error("非法核销");
        }

        int r  =   lvyouScenicTicketOrderService.updateStatusByOrderNo(5, orderNo, 2, null, null);
        if(r > 0){
            lvyouScenicTicketOrder.setStatus(5);
            lvyouScenicTicketOrder.setHexiaoMemberName(lvyouMember.getNickname());
            lvyouScenicTicketOrder.setHexiaoMobile(lvyouMember.getMobile());
            lvyouScenicTicketOrderService.save(lvyouScenicTicketOrder);
            return R.ok("核销成功");
        }else{
            return R.error("核销失败");
        }
    }



    /**
     * http://127.0.0.1/f/scenicspot/order/v1/checkIsHexiaook?orderNo=LV636200068011831296
     * @param request
     * @return
     */
    @RequestMapping("/checkIsHexiaook")
    @ResponseBody
    public R checkIsHexiaook(
            @RequestParam("orderNo") String orderNo,
            HttpServletRequest request){
        LvyouScenicTicketOrder lvyouScenicTicketOrder =  lvyouScenicTicketOrderService.getByOrderNoAndStatus(orderNo, 5);
        if(null == lvyouScenicTicketOrder){
            return R.error("没有核销");
        }else{
            return R.ok("核销成功");
        }
    }



    /**
     * http://127.0.0.1/f/scenicspot/order/v1/get_order_qrcode?orderNo=123456
     * @return
     */
    @RequestMapping("/get_order_qrcode/{orderNo}")
    @ResponseBody
    public void getOrderQrcode(
            @PathVariable String orderNo,
            HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        String  url = orderNo;
        BufferedImage qr = QrcodeUtils.getBarCodeImgByUrl(url,640,640);
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        response.setContentType("image/jpeg");
        ImageIO.write(qr, "jpg", response.getOutputStream());
        response.getOutputStream().flush();
        response.getOutputStream().close();
    }



   /**
     * http://127.0.0.1:8090/f/scenicspot/order/v1/create_order?ticketId=1&ticketDate=2019-10-14&ticketNum=1&spotId=2&memberMobile=15230060935&memberOpenid=oLe7z0IALq_avnCFmt3M3VLjboag
     * @param lvyouScenicTicketOrder
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("create_order")
    public R createOrder(
            LvyouScenicTicketOrder lvyouScenicTicketOrder ,@RequestParam(value = "realName",defaultValue = "") String realName,
            HttpServletRequest request, HttpServletResponse response){
        Object obj  = RequestParCheckUtils.checkPar(lvyouScenicTicketOrder, new String[]{
           "ticketId",
           "ticketDate",
           "ticketNum",
           "spotId",
           "memberMobile",
           "memberOpenid",
        });
        if(!obj.equals(true)){
            return R.error(obj.toString());
        }
        return createOrderFunction(lvyouScenicTicketOrder,realName,request);
    }
    R createOrderFunction(LvyouScenicTicketOrder lvyouScenicTicketOrder,String realName,HttpServletRequest request){
        LvyouMember mmeber = lvyouMemberService.getByOpenid(lvyouScenicTicketOrder.getMemberOpenid());
        LvyouScenicTicket  lvyouScenicTicket =  lvyouScenicTicketService.get(lvyouScenicTicketOrder.getTicketId());
           if(null == lvyouScenicTicket){
               return R.error("门票不存在");
           }
           LvyouScenicTicketMoney lvyouScenicTicketMoney  = lvyouScenicTicketMoneyService.getByNowDate(lvyouScenicTicketOrder.getTicketId(), DateUtils.format(lvyouScenicTicketOrder.getTicketDate()));
           if(null == lvyouScenicTicketMoney){
               return R.error("价格不存在");
           }
           LvyouScenicSpot lvyouScenicSpot = lvyouScenicSpotService.get(lvyouScenicTicketOrder.getSpotId());
           if(null == lvyouScenicSpot){
               return R.error("景点不存在");
           }
           if(!lvyouScenicSpot.getId().equals(lvyouScenicTicket.getSpotId())){
               return R.error("非法请求");
           }
        lvyouScenicTicketOrder.setUserId(lvyouScenicSpot.getUserId());
        lvyouScenicTicketOrder.setUserName(lvyouScenicSpot.getUserName());
        lvyouScenicTicketOrder.setCityId(lvyouScenicSpot.getCityId());
        lvyouScenicTicketOrder.setCityName(lvyouScenicSpot.getCityName());
        lvyouScenicTicketOrder.setMoney(lvyouScenicTicketMoney.getMoney() * lvyouScenicTicketOrder.getTicketNum());
        lvyouScenicTicketOrder.setTicketName(lvyouScenicTicket.getName());
        lvyouScenicTicketOrder.setSpotName(lvyouScenicSpot.getName());
        if(realName==null){

            lvyouScenicTicketOrder.setMemberNickname(mmeber.getNickname());
        }else{
            lvyouScenicTicketOrder.setMemberNickname(realName);
        }

        lvyouScenicTicketOrder.setTotalMoney(lvyouScenicTicketOrder.getTicketNum() * lvyouScenicTicketMoney.getMoney());
        //直接修改为已支付
        lvyouScenicTicketOrder.setStatus(1);
        lvyouScenicTicketOrder.setOrderNo(SnowflakeIdWorker.getOrderNo("LV"));
        Map map = createJsApi(lvyouScenicTicketOrder,request);
        if(null != map){
            int r =  lvyouScenicTicketOrderService.save(lvyouScenicTicketOrder);
            if(r > 0){
                return R.ok().put("jsApi", map);
            }else{
                return R.error("订单创建失败");
            }
        }else{
            return R.error("订单创建失败");
        }

    }


    /**
     * 创建支付jsAPI
     * @param request
     * @return
     */
    Map createJsApi(LvyouScenicTicketOrder order, HttpServletRequest request){
        //随机字符串
        String nonce_str = CommonUtil.CreateNoncestr();
        String basePath = request.getScheme() + "://"
                + request.getServerName() + request.getContextPath();
        WxPayHelper wxPayHelper = new WxPayHelper();
        /*新的商户信息*/
        wxPayHelper.setApiKey(xcxConfigService.getDefalt().getApiKey());
        //小程序id
        wxPayHelper.setAppId(xcxConfigService.getDefalt().getAppId());
        //商户号
        wxPayHelper.setMchId(xcxConfigService.getDefalt().getMemchantNo());

        wxPayHelper.SetParameter("openid",order.getMemberOpenid());
        //商品描述
        wxPayHelper.SetParameter("body", "购买门票消费"+order.getTotalMoney()+"元");
        wxPayHelper.SetParameter("nonce_str", nonce_str);
        //通知地址
        wxPayHelper.SetParameter("notify_url", basePath
                + "/f/scenicspot/order/v1/wxCallBack");
        wxPayHelper.SetParameter("out_trade_no", order.getOrderNo());
        //标价金额
        wxPayHelper.SetParameter("total_fee", String.format("%.0f",order.getMoney()*100));
        //终端IP
        wxPayHelper.SetParameter("spbill_create_ip",
                IPUtils.getIpAddr(request));
        //交易类型
        wxPayHelper.SetParameter("trade_type", "JSAPI");
        wxPayHelper.SetParameter("attach", "购买门票");
        try {
            Map m = wxPayHelper.createPayByJSAPI(xcxConfigService.getDefalt().getAppId());
            return  m;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * http://127.0.0.1/f/scenicspot/order/v1/wxCallBack?orderNo=LV634684683353632768
     * @return
     * @throws Exception
     */
    @RequestMapping("wxCallBack")
    //@ResponseBody
    public void wxCallBack(HttpServletRequest request, HttpServletResponse response) throws Exception {
        if(wxCallBackHander(request, response)) {
            if(null != response.getWriter()) {
                response.getWriter().println(WXPAYOK);
            }
        }else {
            if(null != response.getWriter()) {
                response.getWriter().println(WXPAYNO);
            }
        }
        if(null != response.getWriter()) {
            response.getWriter().flush();
            response.getWriter().close();
        }

    }




    /**
     * 回掉处理防止并发
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    synchronized  boolean  wxCallBackHander(HttpServletRequest request, HttpServletResponse response) throws Exception {

        StringBuffer stringBuffer = new StringBuffer();
        BufferedReader bReader = request.getReader();
        String line = "";
        while ((line = bReader.readLine()) != null) {
            stringBuffer.append(line);
        }
        Map<String, String> xmlMap = XMLUtils.xml2Map(stringBuffer.toString());
        System.err.println("微信回调参数-------------------" + stringBuffer.toString());
        String resXml = null;
        if ("SUCCESS".equals(xmlMap.get("xml.result_code"))) {
            String out_trade_no = xmlMap.get("xml.out_trade_no");
            String total_fee = xmlMap.get("xml.total_fee");
            String transaction_id = xmlMap.get("xml.transaction_id");
            Hog.e("支付回调 时间 = {}，订单号 = {}，微信单号 ={}",
                    DateUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"), out_trade_no, transaction_id);
            if (com.alibaba.druid.util.StringUtils.isEmpty(transaction_id)
                    || com.alibaba.druid.util.StringUtils.isEmpty(total_fee) ||
                    StringUtils.isEmpty(out_trade_no)
            ) {
                return false;
            }
            /**
             * 支付回调参数验证  防止别人恶意篡改回调数据
             */
            if (!PayCheckSginUtils.checkWxSgin(xmlMap, xcxConfigService.getDefalt().getApiKey())) {
                return false;
            }
            int r =  lvyouScenicTicketOrderService.updateStatusByOrderNo(2, out_trade_no,1,transaction_id,null);
            if(r <= 0){
                return false;
            }
            //状态修改成功之后的操作
            return true;
        }
        return  false;
    }

    /**
     * 回掉处理防止并发
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    synchronized  boolean  wxCallBackHanderDev(HttpServletRequest request, HttpServletResponse response) throws Exception {
            String  out_trade_no = request.getParameter("orderNo");
            int r =  lvyouScenicTicketOrderService.updateStatusByOrderNo(2, out_trade_no,1,out_trade_no,null);
            if(r <= 0){
                return false;
            }
            //状态修改成功之后的操作
            return true;
    }


    /**
     * http://127.0.0.1/f/scenicspot/order/v1/create_tk_order?orderNo=LV634684683353632768
     * @param request
     * @param response
     * @return
     */
    @ResponseBody
    @RequestMapping("/create_tk_order")
    public R createTkOrder(
            @RequestParam("orderNo") String orderNo,
            HttpServletRequest request,HttpServletResponse response){
        LvyouScenicTicketOrder lvyouScenicTicketOrder = lvyouScenicTicketOrderService.getByOrderNoAndStatus(orderNo, 2);
        if(null == lvyouScenicTicketOrder){
            return R.error("该订单不允许退款");
        }
        Date now = DateUtils.getCustomTime(0);
        if(!lvyouScenicTicketOrder.getTicketDate().equals(now)){
            if(lvyouScenicTicketOrder.getTicketDate().before(now)){
                return R.error("门票已过期");
            }
        }

        try {
            if(lvyouScenicTicketOrder.getStatus().intValue() == 2){
                lvyouScenicTicketOrder.setStatus(3);
            }
            String r =  createTuikuanPar(lvyouScenicTicketOrder,request);
            lvyouScenicTicketOrderService.save(lvyouScenicTicketOrder);
            Hog.e("退款参=={}",r);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return R.ok("您的退款已提交申请,请耐心等待");
    }


    /**
     * 创建退款js
     * @param order
     * @return
     * @throws Exception
     */
    String createTuikuanPar(LvyouScenicTicketOrder order,HttpServletRequest request) throws Exception{
        XcxConfig xcxConfig =  xcxConfigService.getDefalt();
        String nonce_str = CommonUtil.CreateNoncestr();
        String basePath = request.getScheme() + "://"
                + request.getServerName() + request.getContextPath();
        WxPayHelper wxPayHelper = new WxPayHelper();
        Map map = new HashMap();
        map.put("appid", xcxConfig.getAppId());
        map.put("mch_id", xcxConfig.getMemchantNo());
        map.put("nonce_str", nonce_str);
        map.put("notify_url", basePath
                + "/f/scenicspot/order/v1/wxTuikuanCallBack");
        map.put("transaction_id",order.getPayOrderNo());
        map.put("out_refund_no", SnowflakeIdWorker.getOrderNo("TK"));
        map.put("total_fee", String.format("%.0f",order.getMoney()*100));
        map.put("refund_fee", String.format("%.0f",order.getMoney()*100));
        map.put("sign", MoneyUtils.createSign(map, xcxConfig.getApiKey()));// 签名
        return TuikuanUtils.createTuikuan(map, xcxConfig.getMemchantNo(), xcxConfig.getBookPath());
    }



    @RequestMapping("/wxTuikuanCallBack")
    public void wxTkCallbanck(HttpServletRequest request,HttpServletResponse response) throws Exception {
        if(wxTuikuanCallBackHander(request, response)) {
            if(null != response.getWriter()) {
                response.getWriter().println(WXPAYOK);
            }
        }else {
            if(null != response.getWriter()) {
                response.getWriter().println(WXPAYNO);
            }
        }
        if(null != response.getWriter()) {
            response.getWriter().flush();
            response.getWriter().close();
        }
    }


    /**
     * 回掉处理防止并发
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    synchronized  boolean  wxTuikuanCallBackHander(HttpServletRequest request,HttpServletResponse response) throws Exception{

        StringBuffer stringBuffer = new StringBuffer();
        BufferedReader bReader = request.getReader();
        String line = "";
        while ((line = bReader.readLine()) != null) {
            stringBuffer.append(line);
        }
        Map<String, String> xmlMap = XMLUtils.xml2Map(stringBuffer.toString());
        System.err.println("微信退款回调参数-------------------"+stringBuffer.toString());
        String resXml = null;
        if ("SUCCESS".equals(xmlMap.get("xml.return_code"))) {
            if(xmlMap.containsKey("xml.req_info")) {
                String req_info = xmlMap.get("xml.req_info");
                String jiemi =  AESUtils.decryptData(req_info, xcxConfigService.getDefalt().getApiKey());
                Hog.e("退款回调解密后的参数 = {}",jiemi);
                if(!StringUtils.isEmpty(jiemi)) {
                    Map<String, String> xmlMap2 = XMLUtils.xml2Map(jiemi);
                    if("SUCCESS".equals(xmlMap2.get("root.refund_status"))) {
                       if(StringUtils.isEmpty(xmlMap2.get("root.out_trade_no").toString())){
                           return false;
                       }
                       int r =  lvyouScenicTicketOrderService.updateStatusByOrderNo(4, xmlMap2.get("root.out_trade_no").toString(), 3, null, xmlMap2.get("root.transaction_id").toString());
                       if(r > 0){
                           return true;
                       }
                    }
                }

            }
            return true;
        }
        return false;

    }

}
